﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

using Happy.ExtentionMethods;

namespace Happy.Domain.EntityFramework
{
    /// <inheritdoc />
    public class Repository<TUnitOfWork, TAggregateRoot> : Repository<TUnitOfWork, TAggregateRoot, Guid>
        where TUnitOfWork : UnitOfWork
        where TAggregateRoot : class, IAggregateRoot<Guid>
    {
        /// <summary>
        /// 构造方法。
        /// </summary>
        protected Repository(TUnitOfWork unitOfWork)
            : base(unitOfWork)
        {
        }
    }

    /// <inheritdoc />
    public class Repository<TUnitOfWork, TAggregateRoot, TId> : IRepository<TAggregateRoot, TId>, ISupportQueryable<TAggregateRoot>
        where TUnitOfWork : UnitOfWork
        where TAggregateRoot : class, IAggregateRoot<TId>
    {
        private UnitOfWork _unitOfWork;

        /// <summary>
        /// 构造方法。
        /// </summary>
        protected Repository(TUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        /// <inheritdoc />
        public bool Contains(TAggregateRoot item)
        {
            item.MustNotNull("item");

            return _unitOfWork.Entry(item).State != EntityState.Detached;
        }

        /// <inheritdoc />
        public void Save(TAggregateRoot item)
        {
            item.MustNotNull("item");

            _unitOfWork.Set<TAggregateRoot>().Add(item);
        }

        /// <inheritdoc />
        public void Update(TAggregateRoot item)
        {
            item.MustNotNull("item");

            _unitOfWork.Entry(item).State = EntityState.Modified;
        }

        /// <inheritdoc />
        public void Delete(TAggregateRoot item)
        {
            item.MustNotNull("item");

            _unitOfWork.Entry(item).State = EntityState.Deleted;
        }

        /// <inheritdoc />
        public void Merge(TAggregateRoot item)
        {
            item.MustNotNull("item");

            var persistItem = _unitOfWork.Set<TAggregateRoot>().Find(item.Id);

            _unitOfWork.Entry(persistItem).CurrentValues.SetValues(item);
        }

        /// <inheritdoc />
        public void Detach(TAggregateRoot item)
        {
            item.MustNotNull("item");

            _unitOfWork.Entry(item).State = EntityState.Detached;
        }

        /// <inheritdoc />
        public void Attach(TAggregateRoot item)
        {
            item.MustNotNull("item");

            _unitOfWork.Entry(item).State = EntityState.Unchanged;
        }

        /// <inheritdoc />
        public TAggregateRoot Load(TId id)
        {
            return _unitOfWork.Set<TAggregateRoot>().Find(id);
        }

        /// <inheritdoc />
        public void Refresh(TAggregateRoot item)
        {
            item.MustNotNull("item");

            _unitOfWork.Entry(item).Reload();
        }

        /// <inheritdoc />
        public IUnitOfWork UnitOfWork
        {
            get
            {
                return _unitOfWork;
            }
        }

        /// <inheritdoc />
        public IQueryable<TAggregateRoot> Queryable()
        {
            return _unitOfWork.Set<TAggregateRoot>();
        }

        /// <summary>
        /// 数据库上下文。
        /// </summary>
        protected DbContext DbContext
        {
            get
            {
                return _unitOfWork;
            }
        }
    }
}
